#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <cassert>

namespace me
{
#define LOCAL_SIZE 16
    class string
    {
        typedef char* iterator;
        typedef const char* const_iterator;
    public:
        string(const char* str = "")
        {
            _size = strlen(str);
            /*小于等于16，存放在数组中*/
            if(_size <= LOCAL_SIZE) {
                strcpy(_local_buf, str);
                _capacity = 16;
                _isHeap = false;
            }else {
                _capacity = 2 * _size;
                _heap_ptr = new char[_capacity + 1]; // 实际大小比容量大1，要用来存储/0
                strcpy(_heap_ptr, str);
                _isHeap = true;
            }
        }

        ~string()
        {
            if(_isHeap)
                delete[] _heap_ptr;
        }

        string(const string& s)
        {
            /*构造一个与s一样的string对象*/
            string tmp(s.c_str());
            /*让this与该tmp交换*/
            swap(tmp);
        }

        // s1 = s;
        // 释放s1
        string& operator=(string s)
        {
            swap(s);
            return *this;
        }

        string(string&& s)
        {
            swap(s);
        }

        string& operator=(string&& s)
        {
            swap(s);
            return *this;
        }

        void push_back(char ch)
        {
            if(_size == _capacity) {
                reserve(2*_capacity);
            }
            if(_isHeap) {
                _heap_ptr[_size] = ch;
                _size++;
                _heap_ptr[_size] = '\0';
            }else {
                _local_buf[_size] = ch;
                _size++;
                _local_buf[_size] = '\0';
            }
        }

        void append(const char* s)
        {
            size_t len = strlen(s);
            if(_size + len > _capacity)
                reserve(_size + len > 2 * _capacity ? _size+len : 2 * _capacity);
            if(_isHeap) {
                strcpy(_heap_ptr + _size, s);
            } else {
                strcpy(_local_buf+_size, s);
            }
            _size += len;
        }

        string& operator+=(char ch) { push_back(ch); return *this; }
        string& operator+=(const char* str) { append(str); return *this; }
        char& operator[](size_t pos)
        {
            assert(pos >=0 && pos < _size);
            if(_isHeap) {
                return _heap_ptr[pos];
            }else {
                return _local_buf[pos];
            }
        }
        const char& operator[](size_t pos) const
        {
            assert(pos >=0 && pos < _size);
            if(_isHeap) {
                return _heap_ptr[pos];
            }else {
                return _local_buf[pos];
            }
        }

        iterator begin()
        {
            if(_isHeap) return _heap_ptr;
            else return _local_buf;
        }
        iterator end()
        {
            if(_isHeap) return _heap_ptr + _size;
            else return _local_buf + _size;
        }
        const_iterator cbegin() const
        {
            if(_isHeap) return _heap_ptr;
            else return _local_buf;
        }
        const_iterator cend() const
        {
            if(_isHeap) return _heap_ptr + _size;
            else return _local_buf + _size;
        }

        const char* c_str() const
        {
            if(!_isHeap) return _local_buf;
            else return _heap_ptr;
        }
        size_t size() const { return _size; }
        size_t capacity() const { return _capacity; }
        bool empty() { return !_size; }
        void clear()
        {
            if(_isHeap) *_heap_ptr = '\0';
            else _local_buf[0] = '\0';
            _size = 0;
            _isHeap = true;
        }

        void reserve(size_t n)
        {
            if(n > _capacity) {
                char* tmp = new char[n + 1];
                if(_isHeap) {
                    strcpy(tmp, _heap_ptr);
                    delete _heap_ptr;
                }else {
                    strcpy(tmp, _local_buf);
                }
                _heap_ptr = tmp;
                _isHeap = true;
                _capacity = n;
            }
        }

    private:
        void swap(string& s) 
        {
            std::swap(_size, s._size);
            std::swap(_capacity, s._capacity);
            std::swap(_isHeap, s._isHeap);
            /*这里的交换有问题，需要考虑所有情况
              同时使用堆空间，同时使用栈空间，一个为栈一个为堆
            */

            if(_isHeap)
                std::swap(_heap_ptr, s._heap_ptr);
            else
                std::swap(_local_buf, s._local_buf);
        }

        union
        {
            char* _heap_ptr;     // 长字符串，存储在堆上
            char _local_buf[17]; // 短字符串，存储在栈上16个字符+/0
        };
        size_t _size;            // 当前字符串的长度，不含/0
        size_t _capacity;        // 不使用堆空间，16不含/0；使用堆空间，2倍扩容
        bool _isHeap;            // 是否使用堆空间
        
        static const size_t npos;
    };
    static const size_t npos = -1;
}

int main()
{
    //me::string s;
    //std::string s1;
    //std::cout << sizeof(s1) << std::endl;
    //std::cout << sizeof(char*) << std::endl;
    std::string s("12345511111111111111111(((((((((((((((((1");
    std::cout << s.size() << std::endl;
    std::cout << s.capacity() << std::endl;
    std::vector<int> i;
    return 0;
}